﻿using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using UMLSynthesizer.CSharpAnalyzer.Helpers;
using UMLSynthesizer.LangAnalyzer;
using UMLSynthesizer.LangAnalyzer.Elements;
using UMLSynthesizer.LangAnalyzer.ExtensionMethods;

namespace UMLSynthesizer.CSharpAnalyzer.Elements
{
    class CSharpInterfaceElement : IInterfaceElement
    {
        #region Fields

        IEnumerable<InterfaceDeclarationSyntax> elementNodes;
        CSharpElementContainerHelper containerHelper;
        CSharpElementWithHeritageHelper heritageHelper;
        CSharpElementWithAttributesHelper attributesHelper;

        #endregion

        #region Constructor

        public CSharpInterfaceElement(IEnumerable<InterfaceDeclarationSyntax> elementNodes, IElementBase parentElement)
        {
            if (elementNodes == null)
                throw new ArgumentNullException("elementNodes");
            if (elementNodes.Count() == 0)
                throw new ArgumentException("elementNodes can't be empty");
            if (parentElement == null)
                throw new ArgumentNullException("parentElement");

            this.elementNodes = elementNodes;
            this.ParentElement = parentElement;
            this.ProjectOwner = parentElement.ProjectOwner;
            this.containerHelper = new CSharpElementContainerHelper(this,
                () => elementNodes,
                () => new KeyValuePair<int, SyntaxNode>[0]);
            this.heritageHelper = new CSharpElementWithHeritageHelper(
                (ProjectOwner as CSharpProjectElement), elementNodes);
            this.attributesHelper = new CSharpElementWithAttributesHelper(elementNodes);

            this.MetricDictionary = new Dictionary<LanguageAnalyzer.Metrics, double>();
        }

        #endregion

        #region Properties

        public string Identifier { get { return elementNodes.First().Identifier.ToString(); } }
        public ElementKinds Kind { get { return ElementKinds.Interface; } }
        public IElementBase ParentElement { get; private set; }
        public IProjectElement ProjectOwner { get; private set; }

        public IEnumerable<IClassElement> ContainedClasses { get { return containerHelper.ContainedClasses; } }
        public IEnumerable<IDelegateElement> ContainedDelegates { get { return containerHelper.ContainedDelegates; } }
        public IEnumerable<IEnumElement> ContainedEnums { get { return containerHelper.ContainedEnums; } }
        public IEnumerable<IFieldElement> ContainedFields { get { return containerHelper.ContainedFields; } }
        public IEnumerable<IInterfaceElement> ContainedInterfaces { get { return containerHelper.ContainedInterfaces; } }
        public IEnumerable<IMethodElement> ContainedMethods { get { return containerHelper.ContainedMethods; } }
        public IEnumerable<INamespaceElement> ContainedNamespaces { get { return containerHelper.ContainedNamespaces; } }
        public IEnumerable<IPropertyElement> ContainedProperties { get { return containerHelper.ContainedProperties; } }
        public IEnumerable<IStructElement> ContainedStructs { get { return containerHelper.ContainedStructs; } }

        public IEnumerable<IElementWithHeritageBase> BaseList { get { return heritageHelper.BaseList; } }

        public bool IsAbstract { get { return attributesHelper.IsAbstract; } }
        public bool IsStatic { get { return attributesHelper.IsStatic; } }
        public VisibilityStates Visibility { get { return attributesHelper.Visibility; } }

        public Dictionary<LanguageAnalyzer.Metrics, double> MetricDictionary { get; private set; }

        #endregion
    }
}
